/***************************************************************************
* spidisk_storage.c
*
* Purpose: This is used for USB SPI NORFLASH DISK to access the storage read/write and others operations
*
* Author: 
*
* Date: 2019/08/01
*
* Copyright Generalplus Corp. ALL RIGHTS RESERVED.
*
* Version :
* History :
*
****************************************************************************/
#include <string.h>
#include "project.h"
#include "gplib_mm_gplus.h"
#include "drv_l1_cache.h"
#include "drv_l2_usbd_msdc.h"
#include "driver_l1_cfg.h"
#include "drv_l1_usbd.h"
#include "board_config.h"

static INT32U		ramcurlba;
extern INT32S SPIFC_Flash_disk_initial(void);
extern INT32U spi_flash_part0_offset;
extern INT32U spi_flash_size;
extern INT32S spi_flash_disk_read_sector(INT32U blkno , INT32U blkcnt ,  INT32U buf);
extern INT32S spi_flash_disk_write_sector(INT32U blkno , INT32U blkcnt ,  INT32U buf);
extern void spi_flash_buffer_init(void);

static INT32S SPIDISK_Initial_Storage(void* priv)
{
	int ret;
	ret = SPIFC_Flash_disk_initial();
	return ret;
}

static INT32S SPIDISK_Uninitial_Storage(void* priv)
{
	return 0;
}

static void SPIDISK_GetDrvInfo_Storage(void* priv, STORAGE_DRV_INFO *info)
{
	//DBG_PRINT("total sector %d\r\n", size);
	info->nSectors = spi_flash_size - spi_flash_part0_offset;
	info->nBytesPerSector = 512;
}

static INT32S SPIDISK_ReadSectorDMA (void* priv, INT32U *buf,INT8U ifwait,INT32U seccount)
{
 	INT32S sts =1;
 	
    if(seccount < (spi_flash_size - spi_flash_part0_offset))
    {
        //DBG_PRINT("Read DMA addr 0x%x, len 0x%x\r\n", (gRamDiskPtr + (ramcurlba << 9)), (seccount << 9));
        sts = spi_flash_disk_read_sector(ramcurlba, seccount , (INT32U)buf);
        if(sts==0)
        {
	        ramcurlba += seccount;
	        return 0; 
        }
        else
        {
        	DBG_PRINT("Read SPI lba(%d) return -1\r\n", ramcurlba);
        	return -1;
        }   
    }
    else
    {
    	DBG_PRINT("Read SPI return -1\r\n");
        return -1;
    }
}
			  
static INT32S SPIDISK_WriteSectorDMA(void* priv, INT32U *buf, INT8U ifwait, INT32U seccount)
{
	INT32S sts =1 ;
	
	if((ramcurlba == 0)&&((spi_flash_size-spi_flash_part0_offset)<0x8000))
			return 1;
			
	if(seccount < (spi_flash_size - spi_flash_part0_offset))
	{
		sts = spi_flash_disk_write_sector(ramcurlba, seccount , (INT32U)buf);
		if(sts==0)
		{
			ramcurlba += seccount;
       	 	return 0;
		}
		else
		{
        	DBG_PRINT("Write SPI lba(%d) return -1\r\n", ramcurlba);
        	return -1;		
		}	
	}
	else
	{
    	DBG_PRINT("Write SPI return -1\r\n");
        return -1;	
	}
}

static INT32S	SPIDISK_ReadCmdPhase(void* priv, INT32U lba,INT32U seccount)
{
    ramcurlba = lba;
    return 0;
}

static INT32S 	SPIDISK_ReadEndCmdPhase(void* priv)
{
    //DBG_PRINT("Read end\r\n\r\n");
    ramcurlba = 0;
    return 0;
}

static INT32S	SPIDISK_WriteCmdPhase(void* priv, INT32U lba, INT32U seccount)
{
    //DBG_PRINT("Write start lba %d\r\n", lba);
    ramcurlba = lba;
    return 0;  
}

static INT32S 	SPIDISK_WriteEndCmdPhase(void* priv)
{
   //DBG_PRINT("Write end\r\n\r\n");
	ramcurlba = 0;
    return 0; 
}

static INT32S  SPIDISK_CheckDmaCheckState(void* priv)
{
    //DBG_PRINT("RAMDISK_CheckDmaCheckState\r\n");
    return STORAGE_CHECK_READY;
}

/* RAM disk access functions table */
const MSDC_LUN_STORAGE_DRV SPI_FLASH_DISK_Access =
{
	NULL,						//private data
	SPIDISK_Initial_Storage,    		//init
	SPIDISK_Uninitial_Storage,  		//uninit
	NULL,                      			//insert event
	SPIDISK_GetDrvInfo_Storage, 	//get driver info
	SPIDISK_ReadCmdPhase,       	//read command phase
	SPIDISK_ReadSectorDMA,		//read DMA phase
	SPIDISK_ReadEndCmdPhase,	//read command end phase
	SPIDISK_WriteCmdPhase,		//write command phase
	SPIDISK_WriteSectorDMA,		//write DMA phase
	SPIDISK_WriteEndCmdPhase,	//write command end phase
	SPIDISK_CheckDmaCheckState	//check DMA buffer state
};
